package dingding

import (
	"errors"
	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	dingtalkoauth2_1_0 "github.com/alibabacloud-go/dingtalk/oauth2_1_0"
	dingtalkworkflow_1_0 "github.com/alibabacloud-go/dingtalk/workflow_1_0"
	util "github.com/alibabacloud-go/tea-utils/v2/service"
	"github.com/alibabacloud-go/tea/tea"
	"github.com/astaxie/beego/logs"
	v1 "wonlicsys/api/v1"
	"wonlicsys/constPack"
	"wonlicsys/database"
	"wonlicsys/utils/tool"
)

var allDing *AliDing

type AliDing struct {
	DingAuthClient         *dingtalkoauth2_1_0.Client   //客户端
	AccessToken            string                       //凭据
	DingTalkWorkFlowClient *dingtalkworkflow_1_0.Client //api调用实例
}

func NewAllDingService() error {

	allDing = new(AliDing)

	if err := allDing.InitDing(); err != nil {
		return err
	}
	return nil
}

//获取对象
func GetInstance() *AliDing {
	return allDing
}

// CreateClient @description 使用 Token 初始化账号Client
// @return error
func (aliDing *AliDing) CreateClient() error {

	config := &openapi.Config{}
	config.Protocol = tea.String("https")
	config.RegionId = tea.String("central")

	//初始化客户端
	resultAuth, _err := dingtalkoauth2_1_0.NewClient(config)
	if _err != nil {
		logs.Error(_err, "错误resultAuth--------->")
		return _err
	}
	aliDing.DingAuthClient = resultAuth
	//初始化接口
	resultWorkFlow, _err := dingtalkworkflow_1_0.NewClient(config)
	if _err != nil {
		logs.Error(_err, "错误resultWorkFlow--------->")
		return _err
	}
	aliDing.DingTalkWorkFlowClient = resultWorkFlow
	return nil
}

// InitAccToken @description 初始化钉钉api接口 初始化AccessToken
// @return error
func (aliDing *AliDing) InitAccToken() error {
	req := &dingtalkoauth2_1_0.GetAccessTokenRequest{
		AppKey:    tea.String(v1.Conf.DingAppKey),
		AppSecret: tea.String(v1.Conf.DingAPPSecret),
	}

	var _err error
	res, _err := aliDing.DingAuthClient.GetAccessToken(req)
	if _err != nil {
		return _err
	}
	aliDing.AccessToken = *res.Body.AccessToken
	if err := database.RdbSetExp(constPack.DingAccToken, *res.Body.AccessToken, int(*res.Body.ExpireIn)-60); err != nil {
		return err
	}

	return nil
}

// InitDing @description 初始化钉钉api接口
// @return error
func (aliDing *AliDing) InitDing() error {

	err := aliDing.CreateClient()
	if err != nil {
		return err
	}
	//获取企业内部应用的accessToken
	if err := aliDing.InitAccToken(); err != nil {
		return err
	}
	return nil
}

// GetAccessToken @description  初始化钉钉api接口凭据
//@return error
func (aliDing *AliDing) GetAccessToken() error {
	if ok := database.RdbCheck(aliDing.AccessToken); !ok {
		if err := aliDing.InitAccToken(); err != nil {
			return err
		}
	}
	return nil
}

func (aliDing *AliDing) GetRedisAccessToken() string {
	var (
		AccessToken string
		err         error
	)

	AccessToken, err = database.RdbGet(constPack.DingAccToken)
	if err != nil {
		if err := allDing.InitAccToken(); err != nil {
			logs.Error(err, "错误--------->")
			return ""
		}
	}
	if AccessToken == "" {
		if err := allDing.InitAccToken(); err != nil {
			logs.Error(err, "错误--------->")
			return ""
		}
	}

	return allDing.AccessToken
}

//WorkFlowForms  @Description:  创建或更新审批表单模板
// @return error
func (aliDing *AliDing) CreateWorkFlowForms(processCode string, name string, Description string, components []*dingtalkworkflow_1_0.FormComponent) (string, error) {

	formCreateHeaders := &dingtalkworkflow_1_0.FormCreateHeaders{}
	formCreateHeaders.XAcsDingtalkAccessToken = tea.String(allDing.GetRedisAccessToken())
	//最终请求结构体
	formCreateRequest := &dingtalkworkflow_1_0.FormCreateRequest{
		Name:           tea.String(name),
		Description:    tea.String(Description),
		FormComponents: components,
		ProcessCode:    tea.String(processCode),
	}

	logs.Debug(formCreateRequest, "调试")
	//return "", nil

	res, _err := aliDing.DingTalkWorkFlowClient.FormCreateWithOptions(formCreateRequest, formCreateHeaders, &util.RuntimeOptions{})
	if _err != nil {
		return "", _err
	}

	logs.Debug(res, "调试")
	return *res.Body.Result.ProcessCode, nil
}

//WorkFlowProcessInstances  @Description:  发起OA审批实例
// @return error
func (aliDing *AliDing) WorkFlowProcessInstances(originatorUserId string, processCode string, actionType string, userIds string, allFormComponentValues0Details []*dingtalkworkflow_1_0.StartProcessInstanceRequestFormComponentValues) (string, error) {
	startProcessInstanceHeaders := &dingtalkworkflow_1_0.StartProcessInstanceHeaders{}
	logs.Debug(aliDing.AccessToken, "调试aliDing.AccessToken")
	startProcessInstanceHeaders.XAcsDingtalkAccessToken = tea.String(aliDing.GetRedisAccessToken())
	approvers0 := &dingtalkworkflow_1_0.StartProcessInstanceRequestApprovers{
		ActionType: tea.String(actionType),
		UserIds:    []*string{tea.String(userIds)},
	}
	startProcessInstanceRequest := &dingtalkworkflow_1_0.StartProcessInstanceRequest{
		Approvers:           []*dingtalkworkflow_1_0.StartProcessInstanceRequestApprovers{approvers0},
		OriginatorUserId:    tea.String(originatorUserId), //审批发起人的userId。
		ProcessCode:         tea.String(processCode),      //审批流的唯一码。
		FormComponentValues: allFormComponentValues0Details,
	}

	logs.Debug(startProcessInstanceRequest, "调试开启审批")
	res, _err := aliDing.DingTalkWorkFlowClient.StartProcessInstanceWithOptions(startProcessInstanceRequest, startProcessInstanceHeaders, &util.RuntimeOptions{})
	if _err != nil {
		return "", _err
	}

	logs.Debug(res, "调试")
	return *res.Body.InstanceId, nil
}

type ResGetByMobile struct {
	ErrCode   int    `json:"errcode"`
	ErrMsg    string `json:"errmsg"`
	RequestId string `json:"request_id"`
	Result    User   `json:"result"`
}
type User struct {
	UserId string `json:"userid"`
}

func (aliDing *AliDing) GetByMobile(mobile string) (string, error) {

	var resMobile string
	req := map[string]interface{}{
		"mobile": mobile,
	}
	url := "/topapi/v2/user/getbymobile?access_token=" + allDing.GetRedisAccessToken()
	res, err := tool.DingPostRequest(req, url)
	if err != nil {
		return resMobile, err
	}

	var resMap ResGetByMobile
	if err := tool.StructToStruct(res, &resMap); err != nil {
		return "", err
	}
	logs.Debug(res, resMap, "调试")
	if resMap.ErrCode != 0 || resMap.ErrMsg != "ok" {
		logs.Error(res["errmsg"], "错误--------->")
		return "", errors.New("当前接口失败")
	}
	return resMap.Result.UserId, nil
}
